/*
 * Copyright (c) 2023-2025 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.common.mybatis.injector.methods;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import java.util.List;
import java.util.Optional;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.elsfs.cloud.common.annotations.Spell;

/**
 * 自定义方法：查询某节点的所有子节点（含自身），支持 Wrapper /*
 *
 * @author ：zengmingyong
 */
public class SelectChildTree extends SelectList {

  private static final String SQL_SCRIPT =
      """
         <script>
         WITH RECURSIVE cte AS (
             %s SELECT %s FROM %s %s %s
              UNION
              SELECT m.%s FROM %s m INNER JOIN cte pt ON m.%s=pt.%s
              ) SELECT DISTINCT %s FROM cte %s
      </script>
      """;

  public SelectChildTree(String name) {
    super(name);
  }

  public SelectChildTree() {
    this("selectChildTree");
  }

  @Override
  public MappedStatement injectMappedStatement(
      Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {

    String tableName = tableInfo.getTableName();
    String keyColumn = tableInfo.getKeyColumn(); // 主键列名
    String parentColumn = "parent_id"; // 假设表里有 parent_id 字段
    String columns = tableInfo.getAllSqlSelect();
    List<TableFieldInfo> list = tableInfo.getFieldList();
    String sqlWhereEntityWrapper = sqlWhereEntityWrapper(true, tableInfo);
    Optional<TableFieldInfo> first =
        list.stream()
            .filter(tableFieldInfo -> tableFieldInfo.getField().isAnnotationPresent(Spell.class))
            .findFirst();
    if (first.isEmpty()) {
      sqlWhereEntityWrapper = sqlWhereEntityWrapper(true, tableInfo);
    } else {
      TableFieldInfo info = first.get();
      Spell annotation = info.getField().getAnnotation(Spell.class);
      if (!annotation.isWhere()) {
        sqlWhereEntityWrapper = sqlWhereEntityWrapper(true, tableInfo);
      } else {
        sqlWhereEntityWrapper = sqlWhereEntityWrapper(true, tableInfo, info);
      }
    }

    String sql =
        String.format(
            SQL_SCRIPT,
            sqlFirst(),
            sqlSelectColumns(tableInfo, true),
            tableInfo.getTableName(),
            sqlWhereEntityWrapper,
            sqlComment(),
            String.format("%s", columns.replaceAll(",", ",m.")),
            tableName,
            parentColumn,
            keyColumn,
            columns,
            sqlOrderBy(tableInfo));
    SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);
    return this.addSelectMappedStatementForTable(mapperClass, methodName, sqlSource, tableInfo);
  }
}
